package com.lagou.edu.factory;

import com.alibaba.druid.util.StringUtils;
import com.lagou.edu.annotation.Autowired;
import com.lagou.edu.annotation.Service;
import com.lagou.edu.annotation.Transactional;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author xuqi
 */
public class BeanFactory {

    //作为IOC容器存在
    private static Map<String,Object> map = new HashMap<>();


    static {

        Reflections f = new Reflections("com.lagou.edu");
        Set<Class<?>> set = f.getTypesAnnotatedWith(Service.class);
        for (Class<?> c : set) {
            Object bean = null;
            try {
                bean = c.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            Service annotation = c.getAnnotation(Service.class);
            if (StringUtils.isEmpty(annotation.value())) {
                String[] names = c.getName().split("\\.");

                map.put(names[names.length - 1], bean);
            } else {
                map.put(annotation.value(), bean);
            }
        }

        //循环获取属性
        map.forEach((k, v) -> {
            Class c = v.getClass();
            //获取属性集合
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowired.class)
                        && field.getAnnotation(Autowired.class).required()) {
                    String[] names = field.getType().getName().split("\\.");
                    String name = names[names.length - 1];
                    Method[] methods = c.getMethods();
                    for (int j = 0; j < methods.length; j++) {
                        Method method = methods[j];
                        if (method.getName().equalsIgnoreCase("set" + name)) {
                            try {
                                //将属性放进去
                                method.invoke(v, map.get(name));
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }

            if (c.isAnnotationPresent(Transactional.class)) {
                ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
                Class[] face = c.getInterfaces();//获取类c实现的所有接口
                if (face != null && face.length > 0) {
                    v = proxyFactory.getJdkProxy(v);
                } else {
                    v = proxyFactory.getCglibProxy(v);
                }
            }
            map.put(k, v);
        });

    }


    public static  Object getBean(String id) {
        return map.get(id);
    }

}
